//
// Created by xu on 2024/11/18.
//
#include <libavformat/avformat.h>
#include <SDL.h>

// 采样率
#define SAMPLE_RATE 44100
// 采样格式
#define SAMPLE_FORMAT AUDIO_S16LSB
// 采样大小
#define SAMPLE_SIZE SDL_AUDIO_BITSIZE(SAMPLE_FORMAT)
// 声道数
#define CHANNELS 2
// 音频缓存区的样本数量
#define SAMPLES 1024

#define FILENAME "C:/Users/xu/Desktop/output.pcm"
// 每个样本占用多少字节
#define BYTES_PER_SAMPLE ((SAMPLE_SIZE * CHANNELS) / 8)
// 文件缓冲区大小
#define BUFFER_SIZE (SAMPLES * BYTES_PER_SAMPLE)

typedef struct {
    int len;
    int pullLen;
    Uint8 *data;
} AudioBuffer;

// 回调
void pull_audio_data(void *userdata, Uint8 *stream, int len) {
    av_log(NULL, AV_LOG_INFO, "pull_audio_data: %d\n", len);
    SDL_memset(stream, 0, len);
    AudioBuffer *buffer = (AudioBuffer *) userdata;
    if (buffer->len <= 0) return;
    buffer->pullLen = (len > buffer->len) ? buffer->len : len;
    // 填充数据
    SDL_MixAudio(stream, buffer->data, buffer->pullLen, SDL_MIX_MAXVOLUME);
    buffer->data += buffer->pullLen; // 移动指针
    buffer->len -= buffer->pullLen;
}

int main(int argc, char *argv[]) {
    // 初始化Audio子系统
    if (SDL_Init(SDL_INIT_AUDIO)) {
        av_log(NULL, AV_LOG_INFO, "SDL_Init Error: %s\n", SDL_GetError());
        return -1;
    }
    // 音频参数
    SDL_AudioSpec spec;
    spec.freq = SAMPLE_RATE;
    spec.format = SAMPLE_FORMAT;
    spec.channels = CHANNELS;
    spec.samples = SAMPLES;
    spec.callback = pull_audio_data;
    // 传给回调函数的参数
    AudioBuffer buffer;
    buffer.len = 0;
    buffer.pullLen = 0;
    buffer.data = NULL;
    spec.userdata = &buffer;

    if (SDL_OpenAudio(&spec, NULL)) {
        av_log(NULL, AV_LOG_INFO, "SDL_OpenAudio Error: %s\n", SDL_GetError());
        SDL_Quit();
        return -1;
    }

    // 打开文件
    FILE *f = fopen(FILENAME, "rb");
    if (f < 0) {
        av_log(NULL, AV_LOG_INFO, "Open file failed\n");
        SDL_CloseAudio();
        SDL_Quit();
        return -1;
    }

    SDL_PauseAudio(0);
    Uint8 data[BUFFER_SIZE];
    while (1) {
        if (buffer.len > 0) continue;
        buffer.len = (int) fread(data, 1, BUFFER_SIZE, f);
        if (buffer.len <= 0) {
            int samples = buffer.pullLen / BYTES_PER_SAMPLE;
            int ms = samples * 1000 / SAMPLE_RATE;
            SDL_Delay(ms);
            break;
        }
        buffer.data = data;
    }

    fclose(f);
    // 关闭设备
    SDL_CloseAudio();
    SDL_Quit();
}